/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/math/vector
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AESimdFloat32.inl
// Author:		Gianluca Belardelli
// Date:		10/01/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AESIMDFLOAT32_INL_
#define _AESIMDFLOAT32_INL_

AE_FORCEINLINE AESimdFloat32 AE_CALL AESimdFloat32::FromFloat( const AEFLOAT32 &fValue )
{
	AESimdFloat32 fRes;
	fRes.SetFromFloat( fValue );
	return fRes;
}

AE_FORCEINLINE AESimdFloat32 AE_CALL AESimdFloat32::FromUint16( const AEUINT16 &uiValue )
{
	AESimdFloat32 fRes;
	fRes.SetFromUint16( uiValue );
	return fRes;
}

AE_FORCEINLINE AESimdFloat32 AE_CALL AESimdFloat32::FromUint8( const AEUINT8 &uiValue )
{
	AESimdFloat32 fRes;
	fRes.SetFromUint8( uiValue );
	return fRes;
}

AE_FORCEINLINE AESimdFloat32 AE_CALL AESimdFloat32::FromInt32( const AEINT32 &nValue )
{
	AESimdFloat32 fRes;
	fRes.SetFromInt32( nValue );
	return fRes;
}

AE_FORCEINLINE void AESimdFloat32::operator= ( AESimdFloat32ConstRef fValue )
{
	m_fReal = fValue.m_fReal;
}

AE_FORCEINLINE void AESimdFloat32::SetAdd(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b)
{
	*this = a + b;
}
AE_FORCEINLINE void AESimdFloat32::SetSub(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b)
{
	*this = a - b;
}
AE_FORCEINLINE void AESimdFloat32::SetMul(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b)
{
	*this = a * b;
}

AE_FORCEINLINE void AESimdFloat32::SetAddMul(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b, AESimdFloat32ConstRef c)
{
	*this = a + (b * c);
}
AE_FORCEINLINE void AESimdFloat32::SetSubMul(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b, AESimdFloat32ConstRef c)
{
	*this = a - (b * c);
}

AE_FORCEINLINE void AESimdFloat32::Add(AESimdFloat32ConstRef a)
{
	SetAdd( *this, a );
}
AE_FORCEINLINE void AESimdFloat32::Sub(AESimdFloat32ConstRef a)
{
	SetSub( *this, a );
}
AE_FORCEINLINE void AESimdFloat32::Mul(AESimdFloat32ConstRef a)
{
	SetMul( *this, a );
}

AE_FORCEINLINE void AESimdFloat32::AddMul(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b)
{
	SetAddMul( *this, a, b );
}
AE_FORCEINLINE void AESimdFloat32::SubMul(AESimdFloat32ConstRef a, AESimdFloat32ConstRef b)
{
	SetSubMul( *this, a, b );
}

AE_FORCEINLINE void AESimdFloat32::SetInterpolate( AESimdFloat32ConstRef a, AESimdFloat32ConstRef b, AESimdFloat32ConstRef t )
{
#if 1
	const AESimdFloat32 bminusA = b-a;
	SetAddMul( a, t, bminusA );
#else
	*this = ((getConstant(HK_QUADREAL_1) - t) * a) + (t * b);
#endif
}

template <int N>
AE_FORCEINLINE void AESimdFloat32::SetDot( AEVector4fRefParam fParam1, AEVector4fRefParam fParam2 )
{
	*this = fParam1.GetDot<N>(fParam2);
}

AE_FORCEINLINE AEBOOL32 AESimdFloat32::ApproxEqual( AESimdFloat32ConstRef fValue, AESimdFloat32ConstRef fEpsilon ) const
{
	AESimdFloat32 sfResult;
	sfResult.SetAbs( *this - fValue );
	return sfResult.IsLess( fEpsilon );
}

AE_FORCEINLINE void AESimdFloat32::SetClamped(AESimdFloat32ConstRef fParam1, AESimdFloat32ConstRef fMinVal, AESimdFloat32ConstRef fMaxVal )
{
	// This ensures that if a is NAN, clamped will be maxVal afterwards
	const AEVector4fComparison maxValGtA = fMaxVal.CmpG( fParam1 );
	AESimdFloat32 clamped; 
	clamped.SetSelect( maxValGtA, fParam1, fMaxVal );
	SetMax( fMinVal, clamped );
}

AE_FORCEINLINE const AESimdFloat32 AESimdFloat32::Reciprocal( void ) const
{
	AESimdFloat32 sfResult;
	sfResult.SetReciprocal( *this );
	return sfResult;
}

AE_FORCEINLINE const AESimdFloat32 AE_CALL AESimdFloat32::Convert( const AESingleFloat32 &fValue )
{
	AESimdFloat32 sfResult;
	sfResult.m_fReal = fValue;
	return sfResult;
}

AE_FORCEINLINE AEBOOL32 operator<( AESimdFloat32ConstRef fValueA, AESimdFloat32ConstRef fValueB )
{
	return fValueA.IsLess( fValueB );
}

AE_FORCEINLINE AEBOOL32 operator<( AESimdFloat32ConstRef fValueA, AEFLOAT32 fValueB )
{
	return bool( fValueA.GetReal() < fValueB );
}

AE_FORCEINLINE AEBOOL32 operator<( AEFLOAT32 fValueA, AESimdFloat32ConstRef fValueB )
{
	return bool( fValueA < fValueB.GetReal() );
}

AE_FORCEINLINE AEBOOL32 operator<=( AESimdFloat32ConstRef fValueA, AESimdFloat32ConstRef fValueB )
{
	return fValueA.IsLessEqual( fValueB );
}

AE_FORCEINLINE AEBOOL32 operator<=( AESimdFloat32ConstRef fValueA, AEFLOAT32 fValueB )
{
	return ( fValueA.GetReal() <= fValueB );
}

AE_FORCEINLINE AEBOOL32 operator<=( AEFLOAT32 fValueA, AESimdFloat32ConstRef fValueB )
{
	return ( fValueA <= fValueB.GetReal() );
}

AE_FORCEINLINE AEBOOL32 operator>( AESimdFloat32ConstRef fValueA, AESimdFloat32ConstRef fValueB )
{
	return fValueA.IsGreater( fValueB );
}

AE_FORCEINLINE AEBOOL32 operator>( AESimdFloat32ConstRef fValueA, AEFLOAT32 fValueB )
{
	return bool( fValueA.GetReal() > fValueB );
}

AE_FORCEINLINE AEBOOL32 operator>( AEFLOAT32 fValueA, AESimdFloat32ConstRef fValueB )
{
	return bool( fValueA > fValueB.GetReal() );
}

AE_FORCEINLINE AEBOOL32 operator>=( AESimdFloat32ConstRef fValueA, AESimdFloat32ConstRef fValueB )
{
	return fValueA.IsGreaterEqual( fValueB );
}

AE_FORCEINLINE AEBOOL32 operator>=( AESimdFloat32ConstRef fValueA, AEFLOAT32 fValueB )
{
	return ( fValueA.GetReal() >= fValueB );
}

AE_FORCEINLINE AEBOOL32 operator>=( AEFLOAT32 fValueA, AESimdFloat32ConstRef fValueB )
{
	return ( fValueA >= fValueB.GetReal() );
}

#endif // _AESIMDFLOAT32_INL_
